package com.whz.parameterized;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @Author: sinosoft
 * @Description: 可变参数与泛型
 * @Date: Create in 14:49 2021/5/12
 * @Modified By:
 */
@Slf4j
public class VarargsDemo {

    static void dangerous(List<String>... stringLists) {
        log.info("stringLists: {}", Arrays.toString(stringLists));
        List<Integer> intList = List.of(42);
        Object[] objects = stringLists;
        objects[0] = intList;
        String s = stringLists[0].get(0);
    }
    /*不安全方法 在实际运行中 已经擦除了类型信息 被认为是 Object类型*/
    static <T> T[] toArray(T... args) {
        String name = args.getClass().getName();
        String canonicalName = args.getClass().getCanonicalName();
        String simpleName = args.getClass().getSimpleName();
        log.info("name : {}", name);
        log.info("canonicalName : {}", canonicalName);
        log.info("simpleName : {}", simpleName);
        return args;
    }
    /*不安全方法 返回Object[]类型*/
    static <T> T[] pickTwo(T a, T b, T c) {
        switch (ThreadLocalRandom.current().nextInt(3)) {
            case 0: return toArray(a, b);
            case 1: return toArray(b, c);
            case 2: return toArray(a, c);
        }
        throw new AssertionError("生成随机数失败");
    }

    /*安全方法 返回Object[]类型*/
    static <T> List<T> pickTwo_Safe(T a, T b, T c) {
        switch (ThreadLocalRandom.current().nextInt(3)) {
            case 0: return List.of(a, b);
            case 1: return List.of(b, c);
            case 2: return List.of(a, c);
        }
        throw new AssertionError("生成随机数失败");
    }

    /*安全方法*/
    static <T> List<T> flatten(List<? extends T>... lists) {
        List<T> result = Lists.newArrayList();
        for(List<? extends T> list : lists) {
            result.addAll(list);
        }
        return result;
    }
    /*使用List参数代替可变参数
    * 优势: 编译器可以证明该方法是类型安全的 不必再通过SafeVarargs注解来证明它的安全性
    * 缺点: 客户端调用繁琐一些 运行速度慢一些
    * */
    static <T> List<T> flatten1(List<List<? extends T>> lists) {
        List<T> result = Lists.newArrayList();
        for (List<? extends T> list : lists) {
            result.addAll(list);
        }
        return result;
    }
}
